type RegFunc = (value: string) => boolean;
type RegFuncTwoParam = (value: string, param: string) => boolean;
export interface RegProps {
    email: RegFunc;
    mobile: RegFunc;
    url: RegFunc;
    date: RegFunc;
    dateISO: RegFunc;
    number: RegFunc;
    digits: RegFunc;
    idCard: RegFunc;
    carNo: RegFunc;
    amount: RegFunc;
    chinese: RegFunc;
    letter: RegFunc;
    enOrNum: RegFunc;
    contains: RegFuncTwoParam;
    range: RegFuncTwoParam;
}

/**
 * @name email
 * @alias 验证email
 * @description  是否验证email
 * @return {boolean} 是否验证email
 */
const email: RegProps["email"] = (value) => {
  return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(
    value
  );
};

/**
 * @name mobile
 * @alias 验证手机格式
 * @description  是否手机格式
 * @return {boolean} 是否手机格式
 */
const mobile: RegProps["mobile"] = (value) => {
  return /^1[23456789]\d{9}$/.test(value);
};

/**
 * @name url
 * @alias 验证URL格式
 * @description  是否URL格式
 * @return {boolean} 是否URL格式
 */
const url: RegProps["url"] = (value) => {
  return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
    value
  );
};

/**
 * @name date
 * @alias 验证日期格式
 * @description  是否日期格式
 * @return {boolean} 是否日期格式
 */
const date: RegProps["date"] = (value) => {
  return !/Invalid|NaN/.test(new Date(value).toString());
};

/**
 * @name dateISO
 * @alias 验证ISO类型的日期格式
 * @description  是否ISO类型的日期格式
 * @return {boolean} 是否ISO类型的日期格式
 */
const dateISO: RegProps["dateISO"] = (value) => {
  return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(
    value
  );
};

/**
 * @name number
 * @alias 验证十进制数字
 * @description  是否十进制数字
 * @return {boolean} 是否十进制数字
 */
const number: RegProps["number"] = (value) => {
  return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
};

/**
 * @name digits
 * @alias 验证整数
 * @description  是否验证整数
 * @return {boolean} 是否验证整数
 */
const digits: RegProps["digits"] = (value) => {
  return /^\d+$/.test(value);
};

/**
 * @name idCard
 * @alias 验证身份证号码
 * @description  是否验证身份证号码
 * @return {boolean} 是否验证身份证号码
 */
const idCard: RegProps["idCard"] = (value) => {
  return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
    value
  );
};

/**
 * @name carNo
 * @alias 是否车牌号
 * @description  是否为车牌号
 * @return {boolean} 是否为车牌号
 */
const carNo: RegProps["carNo"] = (value) => {
  // 新能源车牌
  const xreg: RegExp = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
  // 旧车牌
  const creg: RegExp = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
  if (value.length === 7) {
    return creg.test(value);
  } else if (value.length === 8) {
    return xreg.test(value);
  } else {
    return false;
  }
};

/**
 * @name amount
 * @alias 验证是否金额,只允许2位小数
 * @description  是否是否金额
 * @return {boolean} 是否是否金额
 */
const amount: RegProps["amount"] = (value) => {
  //金额，只允许保留两位小数
  return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0.\d{1,2}$/.test(value);
};

/**
 * @name chinese
 * @alias 验证是否为中文
 * @description  是否是否为中文
 * @return {boolean} 是否是否为中文
 */
const chinese: RegProps["chinese"] = (value) => {
  let reg = /^[\u4e00-\u9fa5]+$/gi;
  return reg.test(value);
};

/**
 * @name letter
 * @alias 验证是否为字母
 * @description  是否为字母
 * @return {boolean} 是否为字母
 */
const letter: RegProps["mobile"] = (value) => {
  return /^[a-zA-Z]*$/.test(value);
};

/**
 * @name enOrNum
 * @alias 验证是否只能是字母或者数字
 * @description  是否字母或者数字
 * @return {boolean} 是否字母或者数字
 */
const enOrNum: RegProps["enOrNum"] = (value) => {
  //英文或者数字
  let reg = /^[0-9a-zA-Z]*$/g;
  return reg.test(value);
};

/**
 * @name contains
 * @alias 验证是否包含某个值
 * @param1 {string} 查询的值
 * @param2 {type} 是否包含的值
 * @description  是否包含某个值
 * @return {boolean} 是否包含某个值
 */
const contains: RegProps["contains"] = (value, param) => {
  return value.indexOf(param) >= 0;
};

/**
 * @name range
 * @alias 验证是否包含某个值
 * @param1 {string} 最小值
 * @param2 {string} 最大值
 * @description  是否在当前区间
 * @return {boolean} 是否在当前区间
 */
const range: RegProps["range"] = (value, param) => {
  return value >= param[0] && value <= param[1];
};

export const Reg: RegProps = {
  email,
  mobile,
  url,
  date,
  dateISO,
  number,
  digits,
  idCard,
  carNo,
  amount,
  chinese,
  letter,
  enOrNum,
  contains,
  range,
};
